package com.ztesoft.book.api.controller.wx;

import com.ztesoft.book.common.constant.CommonParamUtil;
import com.ztesoft.book.common.constant.Constant;
import com.ztesoft.book.common.utils.Result;
import com.ztesoft.book.common.utils.jwt.JwtUtil;
import com.ztesoft.book.common.utils.wechat.WechatAccessToken;
import com.ztesoft.book.common.utils.wechat.qo.UrlLinkQO;
import com.ztesoft.book.core.wx.wxminuser.dto.WxMinUserDTO;
import com.ztesoft.book.core.wx.wxminuser.qo.WxMinUserQO;
import com.ztesoft.book.core.wx.wxminuser.service.WxMinUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @Description 微信接口
 * @Author YangFan
 * @Date 2021-07-16 13:50
 */
@Slf4j
@RestController
@RequestMapping("/wx")
public class WechatController {

    @Value("${book.weixin.xcx-appid}")
    private String XCX_APPID;
    @Value("${book.weixin.xcx-secret}")
    private String XCX_SECRET;

    @Resource
    private WxMinUserService wxMinUserService;


    /**
     * 方法功能描述:
     * < 通过临时CODE 获取 小程序OPENID >
     *
     * @param code 【参数 1 注释说明】
     * @return Result                        【返回值 注释说明】
     * @author YangFan
     * @date 2021-07-19 10:43
     */
    @PostMapping("/getSessionByCode")
    public Result getSessionByCode(String code) {
        try {
            Result openIdByJscode = WechatAccessToken.getOpenIdByJscode(code, XCX_APPID, XCX_SECRET);
            return openIdByJscode;
        }
        catch (Exception e) {
            return Result.error("接口【jscode2session】调用异常:" + e.getMessage());
        }
    }


    /**
     * 方法功能描述:
     * < 使用sessionKey解密用户敏感数据 >
     *
     * @param encryptedData 参数说明
     * @param iv            参数说明
     * @param sessionKey    参数说明
     * @return Result
     * @author YangFan
     * @date 2021-07-27 16:42
     */
    @PostMapping("/decryptUserInfo")
    public Result decryptUserInfo(String encryptedData, String iv, String sessionKey) {
        try {
            Map<String, Object> userParm = WechatAccessToken.decryptUserInfo(encryptedData, iv, sessionKey);
            // 小程序用户信息入库或更新
            saveOrUpdateMinUser(userParm);
            return Result.successNoMap(userParm);
        }
        catch (Exception e) {
            return Result.error("接口【decryptUserInfo】调用异常:" + e.getMessage());
        }
    }


    /**
     * 方法功能描述:
     * < 使用code直接获取openid以及敏感数据，相当于 getSessionByCode + decryptUserInfo 接口 >
     *
     * @param code          参数说明
     * @param encryptedData 参数说明
     * @param iv            参数说明
     * @return Result
     * @author YangFan
     * @date 2021-07-27 16:52
     */
    @PostMapping("/getUserInfo")
    public Result getUserInfo(String code, String encryptedData, String iv) {
        try {
            Result resSession = WechatAccessToken.getOpenIdByJscode(code, XCX_APPID, XCX_SECRET);
            if (CommonParamUtil.STRING_F_1.equals(resSession.get(Constant.CODE).toString())) {
                return resSession;
            }
            String session_key = resSession.get("sessionKey").toString();
            Map<String, Object> userParm;
            String currentTimeMillis = String.valueOf(System.currentTimeMillis());
            try {
                userParm = WechatAccessToken.decryptUserInfo(encryptedData, iv, session_key);
                String token = JwtUtil.signUserExt(userParm.get("openid").toString(), currentTimeMillis);
                // 小程序用户信息入库或更新
                saveOrUpdateMinUser(userParm);
                userParm.put("token", token);
            }
            catch (Exception e) {
                return Result.error("接口getUserInfo敏感数据解密出错！");
            }
            return Result.successNoMap(userParm);
        }
        catch (Exception e) {
            return Result.error("接口【getUserInfo】调用异常:" + e.getMessage());
        }
    }


    /**
     * 方法功能描述:
     * < 新增或更新小程序用户 >
     *
     * @param userParm 参数说明
     * @return void
     * @author YangFan
     * @date 2021-07-27 17:17
     */
    private void saveOrUpdateMinUser(Map<String, Object> userParm) {
        // 小程序用户信息入库或更新
        String openId = userParm.get("openId").toString();
        String nickName = userParm.get("nickName").toString();
        String avatarUrl = userParm.get("avatarUrl").toString();
        WxMinUserQO qo = new WxMinUserQO();
        qo.setMinOpenid(openId);
        WxMinUserDTO oldUser = wxMinUserService.findOne(qo);
        if (oldUser == null) {
            // 不存在，插入
            WxMinUserDTO minUser = new WxMinUserDTO();
            minUser.setMinOpenid(openId);
            minUser.setNickName(nickName);
            minUser.setCover(avatarUrl);
            wxMinUserService.saveObject(minUser);
        }
        else {
            // 存在，更新
            oldUser.setNickName(nickName);
            oldUser.setCover(avatarUrl);
            wxMinUserService.updateObject(oldUser);
        }
    }


    /**
     * 方法功能描述:
     * < 获取小程序全局token >
     *
     * @return Result                        【返回值 注释说明】
     * @author YangFan
     * @date 2021-07-19 13:54
     */
    @PostMapping("/getAccessToken")
    public Result getAccessToken() {
        try {
            return WechatAccessToken.getAccessToken(XCX_APPID, XCX_SECRET);
        }
        catch (Exception e) {
            return Result.error("接口【getAccessToken】调用异常:" + e.getMessage());
        }
    }


    /**
     * 方法功能描述:
     * < 获取小程序 URL Link >
     *
     * @param param 【参数 1 注释说明】
     * @return Result                        【返回值 注释说明】
     * @author YangFan
     * @date 2021-07-19 15:10
     */
    @PostMapping("/getUrlLink")
    public Result getUrlLink(@RequestBody UrlLinkQO param) {
        log.info("【getUrlLink接口参数】" + param.toString());
        try {
            return WechatAccessToken.getUrlLink(param, XCX_APPID, XCX_SECRET);
        }
        catch (Exception e) {
            return Result.error("接口【getUrlLink】调用异常:" + e.getMessage());
        }
    }


}



